﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Web;
using System.Windows.Forms;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Wagner.Utilities;

namespace Wagner.SharePoint.Utilities
{
	internal class RunJob : OperationBase
	{
		internal RunJob()
		{}

		internal override void Run()
		{
			// -o RunJob -jobtitle "SPDev: Timer Job Tester" -url http://localhost -pause -debug

			string jobTitle = ValidateParameter("jobtitle", true, null);
			string url = ValidateParameter("url", true, null);
			int timeout = ValidateParameterAsInteger("timeout", false, 2);
			
			RunNow(jobTitle, url, timeout);
		}
		
		private void RunNow(string jobTitle, string url, int timeout)
		{
			using (SPSite site = new SPSite(url))
			{
				Guid jobID = Helper.GetJobID(jobTitle, url);
				SPWebApplication webApp = site.WebApplication;
				SPJobDefinition job = webApp.JobDefinitions[jobID];
				
				SPSchedule saveSchedule = job.Schedule;
				Console.WriteLine("Original schedule: " + job.Schedule.ToString());
				DateTime time1 = DateTime.Now;

				Console.WriteLine("Scheduling job to run now...");
				Console.WriteLine("  Web App:   " + webApp.Name);
				Console.WriteLine("  Job Title: " + job.Title);
				Console.WriteLine("  Job ID:    " + job.Id.ToString());
				Console.WriteLine("  Original schedule: " + job.Schedule.ToString());

				SPMinuteSchedule schedule = new SPMinuteSchedule();
				schedule.BeginSecond = 0;
				schedule.EndSecond = 59;
				schedule.Interval = 1;

				try
				{
					job.Schedule = schedule;
					job.Update();
					Console.WriteLine("  Temp schedule: " + job.Schedule.ToString());
					Console.WriteLine("  Job scheduled to run in the next timer job cycle.");

					DateTime lastRunTime = job.LastRunTime;
					DateTime safetyTime = DateTime.Now.AddMinutes(timeout);

					Console.WriteLine(string.Format("Monitoring job for execution (will abort in {0} minutes):", timeout));
					while (lastRunTime.Equals(job.LastRunTime))
					{
						Console.Write(".");
						System.Threading.Thread.Sleep(1000);

						if (DateTime.Now > safetyTime)
						{
							Console.WriteLine();
							Console.WriteLine("Aborted: Timer job did not execute within the required time limit.");
							return;
						}
					}

					double secondsToRun = DateTime.Now.Subtract(time1).TotalSeconds;
					Console.WriteLine();
					Console.WriteLine(string.Format("Timer job executed within {0} seconds.", secondsToRun));
				}
				catch(Exception ex)
				{
					throw ex;
				}
				finally
				{
					Console.WriteLine("Restoring original job schedule...");
					job.Schedule = saveSchedule;
					job.Update(true);
					Console.WriteLine("done.");
				}

				return;
			}
		}

		internal override string HelpSummary
		{
			get
			{
				return @"
-o RunJob 
     Configures the schedule for a timer job to run almost immediately, and
     then restores original schedule.";
			}
		}

		internal override string HelpDetail
		{
			get
			{
				return HelpSummary + @"
Usage:
  SPDev.exe -o RunJob -jobtitle ""<job title>"" -url <url> -timeout 7
      
    Parameters: 
     -jobtitle ""job title""
       Title of the timer job run immediately.
 
     -url <url>
       Specifies the url of the SharePoint web application on the local machine
       for the timer job to be executed.

     [-timeout] <minutes>
       Number of minutes for the SPDev command to wait for the job to execute
       before giving up and restoring the original configuration. The default
       value is 5 minutes.
  
Examples:
 SPDev.exe -o RunJob -jobtitle ""My Custom Job"" -url http://localhost
";
			}
		}
	
	}
}
